package Driver;

import EventManager.CreateBookingRequest;
import EventManager.RequestProcessor;
import EventManager.RequestStatus;
import Model.Event;
import Model.Person;
import Model.Seat;
import Service.OutputManager;

/**
 * This class impersonates a person and attempts to reserve as many seats as possible for all events until seats run out.
 * @author Yury Kitaev
 *
 */
public class AsyncBot extends Thread 
{
	private Person person;
	
	
	public AsyncBot(Person p)
	{
		person = p;
	}
	
	@Override
	public void run()
	{
		bookAllSeats();
	}
	
	/**
	 * Will attempt to reserve as much seats as possible (calling yield in unexpected places just to be fair and to test the system concorrency handling skills)
	 */
	protected void bookAllSeats()
	{
		for (int i = 0; i < Facade.getCatalog().getEvents().size(); ++i)
		{
			Event e =  Facade.getCatalog().getEvents().get(i);
			OutputManager.println(person.getFirstName() + " will try to register for event " + e.getSpecification().getTitle()  + "(ID " + e.getId() + ")");
			int seat = 0;
			// find a seat
			do 
			{
				seat = 0;
				for (int j = 0; j < e.getVenue().getSeats().size(); ++j)
				{
					Seat s = e.getVenue().getSeats().get(j);
					if (!s.isTaken())
					{
						seat = s.getNumber();
					}
				}
				
				if (seat > 0)
				{
					OutputManager.println(person.getFirstName() + " is trying to get seat " + seat + " for " + e.getSpecification().getTitle()  + "(ID " + e.getId() + ")");
					
					yield(); // Done on purpose to allow someone to grab the seat
					
					CreateBookingRequest r = new CreateBookingRequest(person, e.getId(), seat);
				
					RequestProcessor.process(r);
					
					if (RequestStatus.Sustained == r.getStatus())
					{
						if (seat == r.getBooking().getSeat().getNumber())
						{
							OutputManager.println(person.getFirstName() + " made reservation for " + e.getSpecification().getTitle() + "(ID " + e.getId() + ")" + " for the seat s/he wanted (lucky!)");
						}
						else
						{
							OutputManager.println(person.getFirstName() + " made reservation for " + e.getSpecification().getTitle() + "(ID " + e.getId() + ")" + ", but for a different seat (" + r.getBooking().getSeat().getNumber() + ")");
						}
					}
					else
					{
						OutputManager.println(person.getFirstName() + " failed to get seat " + seat + " - someone got it first, and there are no more left for " +  e.getSpecification().getTitle() + "(ID " + e.getId() + ")");
					}
				}
				yield();
			} while (seat > 0); // loop until seats run out for the event
			yield();
			
		} // loop until events run out
		OutputManager.println(person.getFirstName() + " can find no more events and leaves.");
	}
}
